package org.ricks.log;

import org.ricks.log.pattern.DailyPolicy;
import org.ricks.log.pattern.Policy;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * @author chenwei
 * @Description:
 * @date 2023/1/917:02
 */
public class LogFileWriter {

    /**
     * 配置的存档路径
     */
    private LogPath path;
    /**
     * 当前正在记录的文件引用
     */
    private LogFile logFile;

    private Policy policy;

    public LogFileWriter(LogPath path) throws IOException {
        this.policy = new DailyPolicy();
        this.path = path;
        this.logFile = new LogFile(createNewFile(path.getPath(LocalDateTime.now())));

    }

    /**
     * 输出到文件.
     *
     * @param event 日志消息
     * @param text  输出内容
     */
    public void output(LogEvent event, char[] text) {
        try {
            this.recordToFile(event.getEventTime(), text);
        } catch (Throwable e) {
            // 日志输出到终端时有问题，那就丢掉吧...
            e.printStackTrace();
        }
    }

    /**
     * 记录到文件.
     *
     * @param logTime 日志时间
     * @param text    日志文本
     * @throws IOException 记录时可能会抛出IO异常
     */
    public void recordToFile(LocalDateTime logTime, char[] text) throws IOException {
        this.checkRollover(logTime);
        logFile.writer(text);
        logFile.flush();
    }

    private void checkRollover(final LocalDateTime logTime) throws IOException {
        // 不是同一时间，就要切换输出目标
        boolean result = true;
        result &= policy.continueCurrentFile(logTime.toInstant(ZoneOffset.ofTotalSeconds(8 * 60 * 60)).toEpochMilli());
        if (!result) {
            rollover(logTime);
        }
    }

    private void rollover(LocalDateTime logTime) throws IOException {
        // 关闭上一小时的日志文件
        this.flushAndClose();

        // 创建下一小时的日志文件
        final File file = this.createNewFile(path.getPath(logTime));
        this.logFile = new LogFile(file);
        policy.reset();
    }

    void flushAndClose() throws IOException {
        if (logFile != null) {
            logFile.close();
        }
    }

    /**
     * 创建新的日志文件.
     * <p>
     * 如果文件已存在，直接返回那个文件，不存在才会创建，目录不存在也会自动创建
     *
     * @param path 文件路径
     * @return 日志文件
     * @throws IOException If an I/O error occurred
     */
    private File createNewFile(String path) throws IOException {
        File file = new File(path);
        // 文件已存在，直接返回这个文件
        if (file.exists()) {
            return file;
        }
        // 目录不存在直接创建目录
        File fileParent = file.getParentFile();
        if (fileParent != null && !fileParent.exists()) {
            fileParent.mkdirs();
        }
        // 创建文件
        file.createNewFile();
        return file;
    }
}
